/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.form.compat2.layouts.support; import javax.swing.JSplitPane; import org.openide.nodes.Node; import org.openide.nodes.PropertySupport; import org.openide.util.NbBundle; import org.netbeans.modules.form.util2.NbVersion; import org.netbeans.modules.form.util2.NbVersionNotCompatibleException; import org.netbeans.modules.form.FormEditor; import org.netbeans.modules.form.RADVisualContainer; import org.netbeans.modules.form.RADVisualComponent; /** A design-time support layout for JSplitPane component. * * @author Ian Formanek */ final public class JSplitPaneSupportLayout extends PlainDesignSupportLayout { /** A JDK 1.1 serial version UID */ static final long serialVersionUID = -4531158783548926564L; /** bundle to obtain text information from */ private static final java.util.ResourceBundle bundle = NbBundle.getBundle (JSplitPaneSupportLayout.class); public final static String PROP_SPLIT_POSITION = "splitPosition"; // NOI18N public static final int POS_TOP = 0; public static final int POS_BOTTOM = 1; public static final int POS_LEFT = 2; public static final int POS_RIGHT = 3; private static final JSplitPaneConstraintsDescription topCD = new JSplitPaneConstraintsDescription (POS_TOP); private static final JSplitPaneConstraintsDescription bottomCD = new JSplitPaneConstraintsDescription (POS_BOTTOM); private static final JSplitPaneConstraintsDescription leftCD = new JSplitPaneConstraintsDescription (POS_LEFT); private static final JSplitPaneConstraintsDescription rightCD = new JSplitPaneConstraintsDescription (POS_RIGHT); private EmptyComponent emptyLeft = new EmptyComponent (); private EmptyComponent emptyRight = new EmptyComponent (); /** Assigns this DesignLayout to the specified RADVisualContainer. * @param cont The RADVisualContainer that represents a container that will be * managed by this layout or null as a notification that this layout * is not a designLayout for its current container anymore */ public void setRADContainer (RADVisualContainer cont) { super.setRADContainer (cont); if ((cont != null) && (cont.getFormManager () != null)) { JSplitPane splitPane = (JSplitPane)getContainer (); splitPane.setRightComponent (emptyLeft); splitPane.setLeftComponent (emptyRight); centerSplitPane (); } } /** Returns a description of the constraints for the * specified position. The constraints description object will be used * for adding, getting textual description of the constraints and * the popup menu. * The default implementation just returns the default constraints * description. * @param position The position within the container for which the * constraints description should be returned. */ public ConstraintsDescription getConstraintsDescription(java.awt.Point position) { java.awt.Dimension size = getContainer ().getSize (); int orientation = ((JSplitPane) getContainer ()).getOrientation (); if (orientation == JSplitPane.HORIZONTAL_SPLIT) { if (position.x < size.width / 2) return new JSplitPaneConstraintsDescription (POS_LEFT); else return new JSplitPaneConstraintsDescription (POS_RIGHT); } else { if (position.y < size.height / 2) return new JSplitPaneConstraintsDescription (POS_TOP); else return new JSplitPaneConstraintsDescription (POS_BOTTOM); } } final protected java.awt.Container getContainerHelper () { return getContainer (); } /** Adds specified component to this layout. The constraints for the component * are acquired from the component by method getConstraints(). * If the getConstraints() returns null, a new constraints should be * synthesized, and set in the component via setConstraints(). * @param comp The component to add * @see RADVisualComponent#getConstraints * @see RADVisualComponent#setConstraints * @see #removeComponent */ public void addComponent (RADVisualComponent comp) { JSplitPaneConstraintsDescription cd = (JSplitPaneConstraintsDescription) comp.getConstraints(JSplitPaneSupportLayout.class); if (cd == null) { cd = new JSplitPaneConstraintsDescription (POS_LEFT); comp.setConstraints (JSplitPaneSupportLayout.class, cd); } java.awt.Component visual = getFormManager().getVisualRepresentation(comp); JSplitPane splitPane = (JSplitPane) getContainer (); java.awt.Component c = splitPane.getLeftComponent(); if (c != null) { if (c != emptyLeft && c != emptyRight) { if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) cd = new JSplitPaneConstraintsDescription (POS_RIGHT); else cd = new JSplitPaneConstraintsDescription (POS_BOTTOM); comp.setConstraints (JSplitPaneSupportLayout.class, cd); } } else { c = splitPane.getRightComponent(); if (c != null && c != emptyLeft && c != emptyRight) { if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) cd = new JSplitPaneConstraintsDescription (POS_LEFT); else cd = new JSplitPaneConstraintsDescription (POS_TOP); comp.setConstraints (JSplitPaneSupportLayout.class, cd); } } if ((cd.splitPos == POS_RIGHT) || (cd.splitPos == POS_BOTTOM)) splitPane.setRightComponent (visual); else splitPane.setLeftComponent (visual); centerSplitPane (); // splitPane.addComponentListener } void centerSplitPane () { JSplitPane splitPane = (JSplitPane) getContainer (); java.awt.Dimension size = splitPane.getSize (); if (splitPane.getOrientation () == JSplitPane.HORIZONTAL_SPLIT) splitPane.setDividerLocation (size.width / 2); else splitPane.setDividerLocation (size.height / 2); // splitPane.invalidate (); // splitPane.validate (); // splitPane.repaint (); } /** Removes specified component from this layout. * The default implementation removes the visual representation of the specified comp * from the container. * @param comp The component to remove * @see #addComponent */ public void removeComponent (RADVisualComponent comp) { JSplitPaneConstraintsDescription cd = (JSplitPaneConstraintsDescription)comp.getConstraints(JSplitPaneSupportLayout.class); java.awt.Component visual = getFormManager ().getVisualRepresentation (comp); getContainer ().remove (visual); // find if there is some other component on the same side (which was previously not displayed due to the component // we are removing right now) RADVisualComponent comps[] = getRADContainer ().getSubComponents (); for (int i = 0; i < comps.length; i++) { if (comps [i].equals (comp)) continue; JSplitPaneConstraintsDescription newCd = (JSplitPaneConstraintsDescription)comps[i].getConstraints(JSplitPaneSupportLayout.class); if ((cd.splitPos == POS_RIGHT) || (cd.splitPos == POS_BOTTOM)) { if ((newCd.splitPos == POS_RIGHT) || (newCd.splitPos == POS_BOTTOM)) { java.awt.Component newVisual = getFormManager ().getVisualRepresentation (comps[i]); ((JSplitPane)getContainer()).setRightComponent (newVisual); centerSplitPane (); return; } } else { if ((newCd.splitPos == POS_LEFT) || (newCd.splitPos == POS_BOTTOM)) { java.awt.Component newVisual = getFormManager ().getVisualRepresentation (comps[i]); ((JSplitPane)getContainer()).setLeftComponent (newVisual); centerSplitPane (); return; } } } // if no new component found ==>> set no component if ((cd.splitPos == POS_RIGHT) || (cd.splitPos == POS_BOTTOM)) { ((JSplitPane)getContainer()).setRightComponent (emptyRight); } else { ((JSplitPane)getContainer()).setLeftComponent (emptyLeft); } centerSplitPane (); } /** Generates the code for adding specified component to this layout. * @param comp The component to be added to this layout * @param cont The container that is managed by this layout */ public String generateComponentCode(RADVisualContainer cont, RADVisualComponent comp) { JSplitPaneConstraintsDescription cd = (JSplitPaneConstraintsDescription)comp.getConstraints(JSplitPaneSupportLayout.class); StringBuffer buf = new StringBuffer(); buf.append(createContainerGenName(cont)); boolean horizontalOrientation = true; if (cont.getComponent () instanceof JSplitPane) { horizontalOrientation = (((JSplitPane)cont.getComponent ()).getOrientation () == JSplitPane.HORIZONTAL_SPLIT); } if (horizontalOrientation) { if ((cd.splitPos == POS_LEFT) || (cd.splitPos == POS_TOP)) { buf.append("setLeftComponent ("); // NOI18N } else { buf.append("setRightComponent ("); // NOI18N } } else { if ((cd.splitPos == POS_TOP) || (cd.splitPos == POS_LEFT)) { buf.append("setTopComponent ("); // NOI18N } else { buf.append("setBottomComponent ("); // NOI18N } } buf.append (comp.getName()); buf.append (");\n"); // NOI18N return buf.toString(); } /** Returns the layout's properties for specified component. * @param node the RADVisualComponent of the component which properties we request * @return the layout-specific properties for specified component */ public Node.Property[] getComponentProperties(RADVisualComponent comp) { final RADVisualComponent componentNode = comp; return new Node.Property[] { new PropertySupport.ReadWrite (PROP_SPLIT_POSITION, Integer.TYPE, bundle.getString("PROP_jsplitpanecomp_splitPos"), bundle.getString("HINT_jsplitpanecomp_splitPos")) { public Object getValue () { JSplitPaneConstraintsDescription cd = (JSplitPaneConstraintsDescription)componentNode.getConstraints(JSplitPaneSupportLayout.class); return new Integer (cd.splitPos); } public void setValue (Object val) { if (val instanceof Integer) { Object oldValue = getValue (); JSplitPaneConstraintsDescription cd = (JSplitPaneConstraintsDescription)componentNode.getConstraints(JSplitPaneSupportLayout.class); cd.splitPos = ((Integer)val).intValue (); java.awt.Component visual = getRADContainer ().getFormManager ().getVisualRepresentation (componentNode); if ((cd.splitPos == POS_LEFT) || (cd.splitPos == POS_TOP)) { ((JSplitPane) getContainerHelper ()).setLeftComponent (visual); } else { ((JSplitPane) getContainerHelper ()).setRightComponent (visual); } firePropertyChange (componentNode, PROP_SPLIT_POSITION, oldValue, val); updateContainer (); } else throw new IllegalArgumentException(); } public java.beans.PropertyEditor getPropertyEditor () { int orientation = ((JSplitPane) getContainerHelper ()).getOrientation (); return new SplitPosEditor (orientation == JSplitPane.HORIZONTAL_SPLIT); } }, }; } void updateContainer () { getContainerHelper ().invalidate (); getContainerHelper ().validate (); getContainerHelper ().repaint (); } // ----------------------------------------------------------------------------- // innerclasses public static class SplitPosEditor extends java.beans.PropertyEditorSupport { /** Display Names for alignment. */ protected static final String[] tbNames = new String[] { "Top", "Bottom" }; // NOI18N protected static final String[] lrNames = new String[] { "Left", "Right" }; // NOI18N private boolean horizontal; public SplitPosEditor (boolean horizontal) { this.horizontal = horizontal; } /** @return names of the possible directions */ public String[] getTags () { if (horizontal) return lrNames; else return tbNames; } /** @return text for the current value */ public String getAsText () { int value = ((Integer)getValue ()).intValue (); switch (value) { case POS_TOP: if (!horizontal) return tbNames[0]; else return lrNames[0]; case POS_BOTTOM: if (!horizontal) return tbNames[1]; else return lrNames[1]; case POS_LEFT: if (horizontal) return lrNames[0]; else return tbNames[0]; case POS_RIGHT: if (horizontal) return lrNames[1]; else return tbNames[1]; } return null; } /** Setter. * @param str string equal to one value from directions array */ public void setAsText (String str) { if (str.equals (tbNames[0])) setValue (new Integer (POS_TOP)); else if (str.equals (tbNames[1])) setValue (new Integer (POS_BOTTOM)); else if (str.equals (lrNames[0])) setValue (new Integer (POS_LEFT)); else if (str.equals (lrNames[1])) setValue (new Integer (POS_RIGHT)); } } final static class EmptyComponent extends javax.swing.JComponent { static final long serialVersionUID =4804600714927070059L; public void paint (java.awt.Graphics g) { java.awt.Dimension size = getSize (); g.setColor (java.awt.Color.black); g.drawString ("Empty", size.width / 2, size.height / 2); // NOI18N super.paint (g); } public java.awt.Dimension getPreferredSize () { return new java.awt.Dimension (100, 100); } } // ----------------------------------------------------------------------------- // constraints innerclass /** The ConstraintsDescription class encapsulates constraints data and * operations on a constraints that will be used for adding components * to the layout. */ final public static class JSplitPaneConstraintsDescription extends PlainDesignSupportLayout.PlainSupportConstraintsDescription { /** A JDK 1.1 serial version UID */ static final long serialVersionUID = -9167777002792738110L; /** Netbeans class version */ public static final NbVersion nbClassVersion = new NbVersion (1, 0); // saved from Beta3 (Build 129) public JSplitPaneConstraintsDescription () { this (POS_LEFT); } JSplitPaneConstraintsDescription (int pos) { splitPos = pos; } /** Returns a textual descriptions of constraints represented by this * class. E.g. for BorderLayout, it is a text "Center" or "North". * @return textual descriptions of the constraints */ public String getConstraintsString() { switch (splitPos) { case POS_TOP: return bundle.getString ("MSG_ADD_jsplit_top"); case POS_BOTTOM: return bundle.getString ("MSG_ADD_jsplit_bottom"); case POS_RIGHT: return bundle.getString ("MSG_ADD_jsplit_right"); default: case POS_LEFT: return bundle.getString ("MSG_ADD_jsplit_left"); } } // ----------------------------------------------------------------------------- // Serialization /** Writes the object to the stream. * @param oo output stream to write to * @exception IOException Includes any I/O exceptions that may occur */ public void writeExternal (java.io.ObjectOutput oo) throws java.io.IOException { // store version oo.writeObject (nbClassVersion); oo.writeInt (splitPos); } /** Reads the object from stream. * @param oi input stream to read from * @exception IOException Includes any I/O exceptions that may occur * @exception ClassNotFoundException if the class of the read object is not found */ public void readExternal (java.io.ObjectInput oi) throws java.io.IOException, ClassNotFoundException { org.netbeans.modules.form.FormUtils.DEBUG(">> JSplitPaneConstraintsDescription: readExternal: START"); // NOI18N // check the version NbVersion classVersion = (NbVersion) oi.readObject (); if (!nbClassVersion.isCompatible (classVersion)) throw new NbVersionNotCompatibleException (classVersion, nbClassVersion); splitPos = oi.readInt (); org.netbeans.modules.form.FormUtils.DEBUG("<< JSplitPaneConstraintsDescription: readExternal: END"); // NOI18N } // ----------------------------------------------------------------------------- // XML Persistence /** Called to load property value from specified XML subtree. If succesfully loaded, * the value should be available via the getValue method. * An IOException should be thrown when the value cannot be restored from the specified XML element * @param element the XML DOM element representing a subtree of XML from which the value should be loaded * @exception IOException thrown when the value cannot be restored from the specified XML element */ public void readFromXML (org.w3c.dom.Node element) throws java.io.IOException { if (!XML_SPLIT_PANE_CONSTRAINTS.equals (element.getNodeName ())) { throw new java.io.IOException (); } org.w3c.dom.NamedNodeMap attributes = element.getAttributes (); org.w3c.dom.Node node; node = attributes.getNamedItem (ATTR_POSITION); if (node != null) { String pos = node.getNodeValue (); if (VALUE_LEFT.equals (pos)) splitPos = POS_LEFT; else if (VALUE_RIGHT.equals (pos)) splitPos = POS_RIGHT; else if (VALUE_TOP.equals (pos)) splitPos = POS_TOP; else if (VALUE_BOTTOM.equals (pos)) splitPos = POS_BOTTOM; else splitPos = POS_LEFT; // not recognized => default } } /** Called to store current property value into XML subtree. The property value should be set using the * setValue method prior to calling this method. * @param doc The XML document to store the XML in - should be used for creating nodes only * @return the XML DOM element representing a subtree of XML from which the value should be loaded or null * if the value does not need to save any additional data and can be created using the default constructor */ public org.w3c.dom.Node storeToXML(org.w3c.dom.Document doc) { org.w3c.dom.Element el = doc.createElement (XML_SPLIT_PANE_CONSTRAINTS); switch (splitPos) { case POS_RIGHT: el.setAttribute (ATTR_POSITION, VALUE_RIGHT); break; case POS_BOTTOM: el.setAttribute (ATTR_POSITION, VALUE_BOTTOM); break; case POS_TOP: el.setAttribute (ATTR_POSITION, VALUE_TOP); break; case POS_LEFT: default: el.setAttribute (ATTR_POSITION, VALUE_LEFT); break; } return el; } public static final String XML_SPLIT_PANE_CONSTRAINTS = "JSplitPaneConstraints"; // NOI18N public static final String ATTR_POSITION = "position"; // NOI18N public static final String VALUE_LEFT = "left"; // NOI18N public static final String VALUE_RIGHT = "right"; // NOI18N public static final String VALUE_TOP = "top"; // NOI18N public static final String VALUE_BOTTOM = "bottom"; // NOI18N /** The psoition on the JSplitPane */ int splitPos; } } /* * Log * 17 Gandalf 1.16 2/16/00 Tran Duc Trung FIX: layout constraints * need special treatments during pasting new components into JSplitPane * 16 Gandalf 1.15 2/15/00 Tran Duc Trung FIX: pasting a component * into JSplitPane causes NPE * 15 Gandalf 1.14 1/12/00 Ian Formanek NOI18N * 14 Gandalf 1.13 11/27/99 Patrik Knakal * 13 Gandalf 1.12 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 12 Gandalf 1.11 9/17/99 Ian Formanek Fixed bug 3451 - Working * with JSplitPane is not convenient * 11 Gandalf 1.10 9/12/99 Ian Formanek Fixed bug 3573 - * Reloading JSplitPane project does not work correctly * 10 Gandalf 1.9 6/27/99 Ian Formanek Removed indent parameter * from code generation methods * 9 Gandalf 1.8 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 8 Gandalf 1.7 5/27/99 Ian Formanek Fixed bug 1198 - * JSplitPane in HORIZONTAL mode sets the child components backwards * (duh!). * 7 Gandalf 1.6 5/15/99 Ian Formanek * 6 Gandalf 1.5 5/14/99 Ian Formanek * 5 Gandalf 1.4 5/12/99 Ian Formanek * 4 Gandalf 1.3 5/10/99 Ian Formanek * 3 Gandalf 1.2 5/4/99 Ian Formanek package change * (formeditor -> ..) * 2 Gandalf 1.1 3/29/99 Ian Formanek Uses FormUtils.DEBUG to * print messages * 1 Gandalf 1.0 3/29/99 Ian Formanek * $ */